Different ways to add parentheses¶
Time: O(Nx4N/N(3/2)); Space: O(Nx4N/N(3/2)); medium
Given a string of numbers and operators, return all possible results from computing all the different possible ways to group numbers and operators.
The valid operators are +, - and *.
Example 1:
Input: input = “2-1-1”
Output: [0, 2]
Explanation: * ((2-1)-1) = 0 * (2-(1-1)) = 2
Example 2:
Input: input = “2 * 3 - 4 * 5”
Output: [-34, -14, -10, -10, 10]
Explanation:
(2(3-(45))) = -34
((23)-(45)) = -14
((2(3-4))5) = -10
(2((3-4)5)) = -10
(((23)-4)5) = 10
[7]:
import operator
import re
class Solution1(object):
"""
Time: O(n * 4^n / n^(3/2)) ~= n * Catalan numbers = n * (C(2n, n) - C(2n, n - 1)),
due to the size of the results is Catalan numbers,
and every way of evaluation is the length of the string,
so the time complexity is at most n * Catalan numbers.
Space: O(n * 4^n / n^(3/2)), the cache size of lookup is at most n * Catalan numbers.
"""
def diffWaysToCompute(self, input):
"""
:type input: string
:rtype: List[int]
"""
tokens = re.split('(\D)', input)
nums = list(map(int, tokens[::2]))
ops = list(map({'+': operator.add, '-': operator.sub, '*': operator.mul}.get, tokens[1::2]))
lookup = [[None for _ in range(len(nums))] for _ in range(len(nums))]
def diffWaysToComputeRecu(left, right):
if left == right:
return [nums[left]]
if lookup[left][right]:
return lookup[left][right]
lookup[left][right] = [ops[i](x, y)
for i in range(left, right)
for x in diffWaysToComputeRecu(left, i)
for y in diffWaysToComputeRecu(i + 1, right)]
return lookup[left][right]
return diffWaysToComputeRecu(0, len(nums) - 1)
[23]:
s = Solution1()
input = "2-1-1"
# print(s.diffWaysToCompute(input))
assert s.diffWaysToCompute(input) == [0, 2] or [2, 0]
input = "2*3-4*5"
# print(s.diffWaysToCompute(input)) # [-34, -10, -14, -10, 10]
assert s.diffWaysToCompute(input) == [-34, -14, -10, -10, 10] or [-34, -10, -14, -10, 10]
[24]:
class Solution2(object):
def diffWaysToCompute(self, input):
"""
:type input: string
:rtype: List[int]
"""
lookup = [[None for _ in range(len(input) + 1)] for _ in range(len(input) + 1)]
ops = {'+': operator.add, '-': operator.sub, '*': operator.mul}
def diffWaysToComputeRecu(left, right):
if lookup[left][right]:
return lookup[left][right]
result = []
for i in range(left, right):
if input[i] in ops:
for x in diffWaysToComputeRecu(left, i):
for y in diffWaysToComputeRecu(i + 1, right):
result.append(ops[input[i]](x, y))
if not result:
result = [int(input[left:right])]
lookup[left][right] = result
return lookup[left][right]
return diffWaysToComputeRecu(0, len(input))
[25]:
s = Solution2()
input = "2-1-1"
assert s.diffWaysToCompute(input) == [0, 2] or [2, 0]
input = "2*3-4*5"
# print(s.diffWaysToCompute(input)) # [-34, -10, -14, -10, 10]
assert s.diffWaysToCompute(input) == [-34, -14, -10, -10, 10] or [-34, -10, -14, -10, 10]